package cn.iocoder.yudao.module.enterprise.service.account;

import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.enterprise.controller.admin.account.vo.*;
import cn.iocoder.yudao.module.enterprise.controller.admin.emissionsource.vo.EmissionGaseRespVO;
import cn.iocoder.yudao.module.enterprise.controller.admin.emissionsource.vo.EmissionSourceRespVO;
import cn.iocoder.yudao.module.enterprise.convert.account.AccountSourceConvert;
import cn.iocoder.yudao.module.enterprise.dal.dataobject.account.AccountSourceDO;
import cn.iocoder.yudao.module.enterprise.dal.dataobject.emissionsource.EmissionSourceDO;
import cn.iocoder.yudao.module.enterprise.dal.mysql.account.AccountSourceMapper;
import cn.iocoder.yudao.module.enterprise.service.emissionsource.EmissionSourceService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.module.enterprise.enums.ErrorCodeConstants.ACCOUNT_SOURCE_NOT_EXISTS;

/**
 * 碳排放核算和排放源关联 Service 实现类
 *
 * @author StevenShen
 */
@Service
@Validated
public class AccountSourceServiceImpl implements AccountSourceService {

    @Resource
    private AccountSourceMapper accountSourceMapper;
    @Resource
    private EmissionSourceService emissionSourceService;

    @Override
    public Long createAccountSource(AccountSourceCreateReqVO createReqVO) {
        // 插入
        AccountSourceDO accountSource = AccountSourceConvert.INSTANCE.convert(createReqVO);
        accountSourceMapper.insert(accountSource);
        // 返回
        return accountSource.getId();
    }

    @Override
    public void updateAccountSource(AccountSourceUpdateReqVO updateReqVO) {
        // 校验存在
        validateAccountSourceExists(updateReqVO.getId());
        // 更新
        AccountSourceDO updateObj = AccountSourceConvert.INSTANCE.convert(updateReqVO);
        accountSourceMapper.updateById(updateObj);
    }

    @Override
    public void deleteAccountSource(Long id) {
        // 校验存在
        validateAccountSourceExists(id);
        // 删除
        accountSourceMapper.deleteById(id);
    }

    private void validateAccountSourceExists(Long id) {
        if (accountSourceMapper.selectById(id) == null) {
            throw exception(ACCOUNT_SOURCE_NOT_EXISTS);
        }
    }

    @Override
    public PageResult<AccountSourceRespVO> getAccountSourcePage(AccountSourcePageReqVO pageReqVO) {
        List<AccountSourceDO> accountSourceList = accountSourceMapper.selectListByAccountId(pageReqVO.getAccountId());
        if (CollUtil.isEmpty(accountSourceList)) {
            return PageResult.empty();
        }
        List<AccountSourceRespVO> respVOList = AccountSourceConvert.INSTANCE.convertList(accountSourceList);

        // 获取排放源信息
        List<Long> emissionSourceIds = convertList(accountSourceList, AccountSourceDO::getSourceId);
        Map<Long, EmissionSourceDO> emissionSourceMap = emissionSourceService.getEmissionSourceMap(emissionSourceIds);

        // 根据排放源分类过滤数据
        if (pageReqVO.getIsoCategory() != null) {
            emissionSourceMap = emissionSourceMap.entrySet().stream()
                    .filter(e -> e.getValue().getIsoCategory().equals(pageReqVO.getIsoCategory()))
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        } else if (pageReqVO.getGhgCategory() != null) {
            emissionSourceMap = emissionSourceMap.entrySet().stream()
                    .filter(e -> e.getValue().getGhgCategory().equals(pageReqVO.getGhgCategory()))
                    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        }
        Map<Long, EmissionSourceDO> finalEmissionSourceMap = emissionSourceMap;

        respVOList = respVOList.stream().filter(e -> finalEmissionSourceMap.keySet().contains(e.getSourceId())).collect(Collectors.toList());

        // 拼接结果
        respVOList = respVOList.stream()
                .skip((long) (pageReqVO.getPageNo() - 1) * pageReqVO.getPageSize())
                .limit(pageReqVO.getPageSize()).collect(Collectors.toList());

        respVOList = respVOList.stream().map(e -> {
            EmissionSourceDO emissionSourceDO = finalEmissionSourceMap.get(e.getSourceId());
            e.setName(emissionSourceDO.getName())
                    .setDataUnit(emissionSourceDO.getDataUnit())
                    .setFacility(emissionSourceDO.getFacility())
                    .setTotal(this.getEmissionAccount(new AccountEmissionReqVO()
                            .setSourceId(e.getSourceId())
                            .setData(e.getDataValue())));
            return e;
        }).collect(Collectors.toList());

        return new PageResult<AccountSourceRespVO>().setList(respVOList).setTotal((long) respVOList.size());
    }

    @Override
    public Double getEmissionAccount(AccountEmissionReqVO reqVO) {
        EmissionSourceRespVO emissionSourceDO = emissionSourceService.getEmissionSource(reqVO.getSourceId());
        // 因子数值
        Double co2e = emissionSourceDO.getCo2e();
        // 换算比例
        Double unitConversion = emissionSourceDO.getUnitConversion();
        // 活动数据
        Double data = reqVO.getData();

        return co2e * data * unitConversion;
    }

    @Override
    public List<AccountSourceDO> getAccountSourceListByAccountId(Long accountId) {
        return accountSourceMapper.selectListByAccountId(accountId);
    }

    @Override
    public List<AccountSourceDetailRespVO> getAccountSourceDetailList(Long accountId) {
        List<AccountSourceDO> accountSourceList = accountSourceMapper.selectListByAccountId(accountId);
        // 查询排放源信息
        List<Long> sourceIds = convertList(accountSourceList, AccountSourceDO::getSourceId);
        Map<Long, EmissionSourceDO> emissionSourceMap = emissionSourceService.getEmissionSourceMap(sourceIds);
        // 拼接排放源信息
        List<AccountSourceDetailRespVO> respList = new ArrayList<>();
        for (AccountSourceDO accountSource : accountSourceList) {
            AccountSourceDetailRespVO respVO = new AccountSourceDetailRespVO();
            // 从Map中获取排放源
            EmissionSourceDO emissionSource = emissionSourceMap.get(accountSource.getSourceId());
            respVO.setSourceId(accountSource.getSourceId())
                    .setDataValue(accountSource.getDataValue())
                    .setName(emissionSource.getName())
                    .setFacility(emissionSource.getFacility())
                    .setGhgCategory(emissionSource.getGhgCategory())
                    .setGhgClassification(emissionSource.getGhgClassification())
                    .setIsoCategory(emissionSource.getIsoCategory())
                    .setIsoClassification(emissionSource.getIsoClassification())
                    .setDataScore(emissionSource.getDataScore())
                    .setFactorScore(emissionSource.getFactorScore())
                    .setCo2e(emissionSource.getCo2e())
                    .setGwp(emissionSource.getGwp())
                    .setEmissionTotal(emissionSource.getCo2e() * accountSource.getDataValue());
            respList.add(respVO);
        }
        return respList;
    }

    @Override
    public AccountSimulationRespVO simulationAccount(List<AccountSimulationReqVO.SourceSimulation> sourceSimulationList) {
        AccountSimulationRespVO respVO = new AccountSimulationRespVO();
        List<AccountSimulationRespVO.AccountSimulation> accountSimulationList = new ArrayList<>();
        AccountSimulationRespVO.AccountSimulation accountSimulation;

        // 求碳排放总量
        double total = 0D;
        for (AccountSimulationReqVO.SourceSimulation sourceSimulation : sourceSimulationList) {
            Long sourceId = sourceSimulation.getSourceId();
            Double dataValue = sourceSimulation.getDataValue();
            // 获取排放源信息
            EmissionSourceRespVO emissionSource = emissionSourceService.getEmissionSource(sourceId);
            String isoClassification = emissionSource.getIsoClassification();
            // 排放分类-排放源-排放量
            accountSimulation = new AccountSimulationRespVO.AccountSimulation();
            accountSimulation.setSource(isoClassification)
                    .setTarget(emissionSource.getName())
                    .setValue(emissionSource.getCo2e() * dataValue);
            accountSimulationList.add(accountSimulation);
            total += emissionSource.getCo2e() * dataValue;
            // 获取排放源的气体组成
            List<EmissionGaseRespVO> emissionGaseList = emissionSource.getEmissionGaseList();
            // 排放源-气体-排放量
            for (EmissionGaseRespVO emissionGase : emissionGaseList) {
                if (emissionGase.getValue() != null) {
                    accountSimulation = new AccountSimulationRespVO.AccountSimulation();
                    accountSimulation.setSource(emissionSource.getName())
                            .setTarget(emissionGase.getName())
                            .setValue(emissionGase.getValue() * emissionGase.getGwp() * dataValue);
                    accountSimulationList.add(accountSimulation);
                }
            }
        }
        respVO.setEmissionList(accountSimulationList);
        respVO.setTotal(total);
        return respVO;
    }
}
